<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.1.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/themes/green/pace-theme-minimal.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/pace.min.js" integrity="sha256-gqd7YTjg/BtfqWSwsJOvndl0Bxc8gFImLEkXQT8+qj0=" crossorigin="anonymous"></script>

<script class="next-config" data-name="main" type="application/json">{"hostname":"liukairui.me","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.10.1","exturl":false,"sidebar":{"position":"left","display":"hide","padding":18,"offset":12},"copycode":true,"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":true,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":false,"nav":null,"activeClass":"valine"},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="此版为JavaScript进阶版，以讲述原理为主,主讲:尚硅谷张晓飞,视频来自B站:BV14s411E7qf与BV1MJ41197Eu">
<meta property="og:type" content="article">
<meta property="og:title" content="JavaScript进阶版笔记">
<meta property="og:url" content="http://liukairui.me/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/">
<meta property="og:site_name" content="LiuKairui Website">
<meta property="og:description" content="此版为JavaScript进阶版，以讲述原理为主,主讲:尚硅谷张晓飞,视频来自B站:BV14s411E7qf与BV1MJ41197Eu">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2020-11-19T17:35:50.000Z">
<meta property="article:modified_time" content="2021-10-18T06:44:13.595Z">
<meta property="article:author" content="Liu Kairui">
<meta property="article:tag" content="前端">
<meta property="article:tag" content="笔记">
<meta property="article:tag" content="JavaScript">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="http://liukairui.me/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"http://liukairui.me/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/","path":"article/JavaScript进阶版笔记/","title":"JavaScript进阶版笔记"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>JavaScript进阶版笔记 | LiuKairui Website</title>
  

  <script src="/js/third-party/analytics/baidu-analytics.js"></script>
  <script async src="https://hm.baidu.com/hm.js?ea07bceb8f5fa721da2ebf01833faa32"></script>



<div class="nindexBK">
<div class="nindexBKC"></div>
<div class="nindex">
  <h1>Hey👋</h1>
  <p style="font-weight: 500; font-size: 2.2em">欢迎访问Liu Kairui的个人站.</p>
  <p>
      我是一个来自重庆的在校大学生, 偏爱于前端技术<!--与OS设计-->, 偶尔使用 JS / Go 进行轻量项目开发, 欢迎访问我的
      <a href="https://github.com/KairuiLiu" target="_blank"><i class="fab fa-github-alt"></i> GitHub</a> .
  </p>
  <p>
      这个网站主要用来存储学习 / 瞎搞的笔记, 同时提供了邮件、图床等服务. 对于一些自认为有趣的<a href="javascript:;" id="myProj">项目</a>, 我也会将项目介绍, 文档, 甚至是设计指南发布在这里.
  </p>
  <ul>
    <li><p><a href="/artrank/" target="_blank">ArtRank</a>: 基于Node.JS的PageRank文献管理推荐系统</p></li>
    <li><p><a href="/gooj/" target="_blank">GoOJ</a>: 基于Golang的高校在线评测系统</p></li>
    <li><p><a href="/projects/" target="_blank">更多 <i class="fas fa-angle-right"></i></a></p></li>

  </ul>
  <p>
      可以在这些平台找到我: 
      <a href="https://www.zhihu.com/people/liu-kai-rui-18" target="_blank">知乎</a>,
      <a href="https://space.bilibili.com/33238144" target="_blank">bilibili</a>
      和
      <a href="https://www.coolapk.com/u/805314?from=qr" target="_blank">酷安</a>.
  </p>

  <p>
      下滑即可进入博客 <i class="fas fa-arrow-down"></i>
  </p>
</div>
</div>  

 
<script>
  var OriginTitile = document.title;
  var titleTime;
  document.addEventListener("visibilitychange", function() {
    if (document.hidden) {
      document.title = "谢谢离开 | " + OriginTitile;
      clearTimeout(titleTime);
    } else {
      document.title = "欢迎归来 | " + OriginTitile;
      titleTime = setTimeout(function() {
        document.title = OriginTitile;
      }, 2000);
    }
  });
</script>


<script>
  function checkIndex(){
    let nindexItems = [[".nindexBK","display","block","none"],[".headband","display","none","block"],["div.toggle.sidebar-toggle","visibility","hidden","visible"]]; // ,["button.darkmode-toggle","visibility","hidden","visible"]];
    let isIndex = new RegExp("^(\/){0,1}(index){0,1}(\.html){0,1}(/)*$").test(location.pathname);
    let backCanvas = document.querySelector(".nindexBK");
    nindexItems.dispShift = function (stat){this.forEach((e) => {try{document.querySelector(e[0]).style[e[1]]=e[2+stat];}catch{}})}
    if(isIndex){
      nindexItems.dispShift(0);
      window.onscroll=function(){
        if(document.documentElement.scrollTop>backCanvas.offsetHeight*1.05){
          nindexItems.dispShift(1);window.onscroll=null;
        }
      }
      document.querySelector("#myProj").onclick=()=>{
        let projlist = document.querySelector(".nindex>ul");
        projlist.className.indexOf("ulactive")==-1?projlist.classList.add("ulactive"):projlist.classList.remove("ulactive")
      }
    }else nindexItems.dispShift(1);
  }
  checkIndex();
</script>

<!--<script src="https://sdk.jinrishici.com/v2/browser/jinrishici.js" charset="utf-8"></script>-->

  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
<link rel="alternate" href="/atom.xml" title="LiuKairui Website" type="application/atom+xml">
<style>.darkmode--activated{--body-bg-color:#282828;--content-bg-color:#333;--card-bg-color:#555;--text-color:#ccc;--blockquote-color:#bbb;--link-color:#ccc;--link-hover-color:#eee;--brand-color:#ddd;--brand-hover-color:#ddd;--table-row-odd-bg-color:#282828;--table-row-hover-bg-color:#363636;--menu-item-bg-color:#555;--btn-default-bg:#222;--btn-default-color:#ccc;--btn-default-border-color:#555;--btn-default-hover-bg:#666;--btn-default-hover-color:#ccc;--btn-default-hover-border-color:#666;--highlight-background:#282b2e;--highlight-foreground:#a9b7c6;--highlight-gutter-background:#34393d;--highlight-gutter-foreground:#9ca9b6}.darkmode--activated img{opacity:.75}.darkmode--activated img:hover{opacity:.9}.darkmode--activated code{color:#69dbdc;background:0 0}button.darkmode-toggle{z-index:9999}.darkmode-ignore,img{display:flex!important}</style></head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">LiuKairui Website</p>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">要有信仰</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu">
        <li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li>
        <li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li>
        <li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fas fa-hashtag fa-fw"></i>标签</a></li>
        <li class="menu-item menu-item-收藏夹"><a href="/favorites/" rel="section"><i class="fab fa-gratipay fa-fw"></i>收藏夹</a></li>
        <li class="menu-item menu-item-留言板"><a href="/messageBoard/" rel="section"><i class="fab fa-facebook-messenger fa-fw"></i>留言板</a></li>
        <li class="menu-item menu-item-项目"><a href="/projects/" rel="section"><i class="fa fa-satellite fa-fw"></i>项目</a></li>
        <li class="menu-item menu-item-图床"><a href="http://img.liukairui.me/" rel="noopener" target="_blank"><i class="fa fa-bed fa-fw"></i>图床</a></li>
        <li class="menu-item menu-item-云ide"><a href="http://vsc.liukairui.me/" rel="noopener" target="_blank"><i class="fas fa-code fa-fw"></i>云IDE</a></li>
        <li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a></li>
        <li class="menu-item menu-item-邮箱"><a href="http://mail.liukairui.me/mail" rel="noopener" target="_blank"><i class="fas fa-envelope-open-text fa-fw"></i>邮箱</a></li>
        <li class="menu-item menu-item-rss"><a href="/atom.xml" rel="section"><i class="fa fa-rss fa-fw"></i>RSS</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B"><span class="nav-number">1.</span> <span class="nav-text">数据类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E5%8F%98%E9%87%8F%E4%B8%8E%E5%86%85%E5%AD%98"><span class="nav-number">2.</span> <span class="nav-text">数据,变量,与内存</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AF%B9%E8%B1%A1"><span class="nav-number">3.</span> <span class="nav-text">对象</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0"><span class="nav-number">4.</span> <span class="nav-text">函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0"><span class="nav-number">5.</span> <span class="nav-text">回调函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#iife"><span class="nav-number">6.</span> <span class="nav-text">IIFE</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E4%B8%AD%E7%9A%84this"><span class="nav-number">7.</span> <span class="nav-text">函数中的this</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#js%E7%9A%84%E5%88%86%E5%8F%B7%E9%97%AE%E9%A2%98"><span class="nav-number">8.</span> <span class="nav-text">JS的分号问题</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#prototype"><span class="nav-number">9.</span> <span class="nav-text">prototype</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%98%BE%E5%BC%8F%E5%8E%9F%E5%9E%8B%E4%B8%8E%E9%9A%90%E5%BC%8F%E5%8E%9F%E5%9E%8B"><span class="nav-number">10.</span> <span class="nav-text">显式原型与隐式原型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8E%9F%E5%9E%8B%E9%93%BE"><span class="nav-number">11.</span> <span class="nav-text">原型链</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E5%8E%9F%E5%9E%8B%E7%AD%89%E5%8E%9F%E5%9E%8B%E9%93%BE%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB%E5%9B%BE%E4%B8%8E%E8%A7%A3%E9%87%8A"><span class="nav-number">12.</span> <span class="nav-text">构造函数,原型等原型链之间的关系图与解释</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8E%9F%E5%9E%8B%E9%93%BE%E7%9A%84%E5%B1%9E%E6%80%A7"><span class="nav-number">13.</span> <span class="nav-text">原型链的属性</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87"><span class="nav-number">14.</span> <span class="nav-text">执行上下文</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%8E%E4%BD%9C%E7%94%A8%E5%9F%9F%E9%93%BE"><span class="nav-number">15.</span> <span class="nav-text">作用域与作用域链</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BE%AA%E7%8E%AF%E5%8F%98%E9%87%8F%E7%9B%91%E5%90%AC"><span class="nav-number">16.</span> <span class="nav-text">循环变量监听</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%97%AD%E5%8C%85"><span class="nav-number">17.</span> <span class="nav-text">闭包</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%88%A9%E7%94%A8%E9%97%AD%E5%8C%85%E5%AE%9E%E7%8E%B0js%E6%A8%A1%E5%9D%97"><span class="nav-number">18.</span> <span class="nav-text">利用闭包实现js模块</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E5%AD%98%E6%BA%A2%E5%87%BA%E4%B8%8E%E6%B3%84%E6%BC%8F"><span class="nav-number">19.</span> <span class="nav-text">内存溢出与泄漏</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%88%9B%E5%BB%BA%E6%A8%A1%E5%BC%8F"><span class="nav-number">20.</span> <span class="nav-text">对象的创建模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF%E6%A8%A1%E5%BC%8F-%E5%8E%9F%E5%9E%8B%E9%93%BE%E7%9A%84%E7%BB%A7%E6%89%BF"><span class="nav-number">21.</span> <span class="nav-text">继承模式: 原型链的继承</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF%E6%A8%A1%E5%BC%8F%E5%80%9F%E7%94%A8%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E7%BB%A7%E6%89%BF"><span class="nav-number">22.</span> <span class="nav-text">继承模式:借用构造函数继承</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF%E6%A8%A1%E5%BC%8F-%E7%BB%84%E5%90%88%E7%BB%A7%E6%89%BF"><span class="nav-number">23.</span> <span class="nav-text">继承模式: 组合继承</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A4%8D%E4%B9%A0"><span class="nav-number">24.</span> <span class="nav-text">复习</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B%E4%B8%8E%E7%BA%BF%E7%A8%8B"><span class="nav-number">25.</span> <span class="nav-text">进程与线程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%86%85%E6%A0%B8"><span class="nav-number">26.</span> <span class="nav-text">浏览器内核</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%85%B3%E4%BA%8E%E5%AE%9A%E6%97%B6%E5%99%A8"><span class="nav-number">27.</span> <span class="nav-text">关于定时器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%AA%8C%E8%AF%81js%E6%98%AF%E5%8D%95%E7%BA%BF%E7%A8%8B%E6%89%A7%E8%A1%8C%E7%9A%84"><span class="nav-number">28.</span> <span class="nav-text">验证JS是单线程执行的</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BA%8B%E4%BB%B6%E5%BE%AA%E7%8E%AF%E6%A8%A1%E5%9E%8B"><span class="nav-number">29.</span> <span class="nav-text">事件循环模型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#h5-web-workers"><span class="nav-number">30.</span> <span class="nav-text">H5 Web Workers</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#promise"><span class="nav-number">31.</span> <span class="nav-text">Promise</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#js%E8%AF%AD%E6%B3%95%E5%87%86%E5%A4%87"><span class="nav-number">31.1.</span> <span class="nav-text">JS语法准备</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AE%9E%E4%BE%8B%E5%AF%B9%E8%B1%A1%E4%B8%8E%E5%87%BD%E6%95%B0%E5%AF%B9%E8%B1%A1"><span class="nav-number">31.1.1.</span> <span class="nav-text">实例对象与函数对象</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E7%9A%84callapplybind%E6%96%B9%E6%B3%95"><span class="nav-number">31.1.2.</span> <span class="nav-text">函数的call&#x2F;apply&#x2F;bind方法</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%B8%A4%E7%A7%8D%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0"><span class="nav-number">31.1.3.</span> <span class="nav-text">两种类型的回调函数</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86"><span class="nav-number">31.1.4.</span> <span class="nav-text">错误处理</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#promise%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">31.2.</span> <span class="nav-text">Promise的使用</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%98%AF%E4%BB%80%E4%B9%88"><span class="nav-number">31.2.1.</span> <span class="nav-text">是什么</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E4%BD%BF%E7%94%A8promise"><span class="nav-number">31.2.2.</span> <span class="nav-text">为什么要使用Promise</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8promise"><span class="nav-number">31.2.3.</span> <span class="nav-text">如何使用Promise</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%89%8B%E5%86%99promise"><span class="nav-number">31.3.</span> <span class="nav-text">手写Promise</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#asyncawait"><span class="nav-number">31.4.</span> <span class="nav-text">async&amp;await</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%8F%E9%98%9F%E5%88%97%E4%B8%8E%E5%BE%AE%E9%98%9F%E5%88%97"><span class="nav-number">31.5.</span> <span class="nav-text">宏队列与微队列</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%9D%A2%E8%AF%95%E9%A2%98"><span class="nav-number">31.6.</span> <span class="nav-text">面试题</span></a></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Liu Kairui"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">Liu Kairui</p>
  <div class="site-description" itemprop="description">LiuKairui Persional Website</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">45</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">24</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">53</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author site-overview-item animated">
      <span class="links-of-author-item">
        <a href="https://github.com/KairuiLiu" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;KairuiLiu" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:tclkr@live.com" title="E-Mail → mailto:tclkr@live.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://qm.qq.com/cgi-bin/qm/qr?k=oaf3ToOlN17hr5sHV98bT8qxsNYGaw5L&noverify=0" title="QQ → https:&#x2F;&#x2F;qm.qq.com&#x2F;cgi-bin&#x2F;qm&#x2F;qr?k&#x3D;oaf3ToOlN17hr5sHV98bT8qxsNYGaw5L&amp;noverify&#x3D;0" rel="noopener" target="_blank"><i class="fab fa-qq fa-fw"></i>QQ</a>
      </span>
      <span class="links-of-author-item">
        <a href="/atom.xml" title="RSS → &#x2F;atom.xml"><i class="fa fa-rss fa-fw"></i>RSS</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://liukairui.blog.csdn.net/" title="CSDN → https:&#x2F;&#x2F;liukairui.blog.csdn.net" rel="noopener" target="_blank"><i class="fab fa-cuttlefish fa-fw"></i>CSDN</a>
      </span>
      <span class="links-of-author-item">
        <a href="http://liukairui.cc/" title="国内站点 → http:&#x2F;&#x2F;liukairui.cc" rel="noopener" target="_blank"><i class="fa fa-globe fa-fw"></i>国内站点</a>
      </span>
  </div>
  <div class="cc-license site-overview-item animated" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="https://cdnjs.cloudflare.com/ajax/libs/creativecommons-vocabulary/2020.11.3/assets/license_badges/small/by_nc_sa.svg" alt="Creative Commons"></a>
  </div>


  <div class="links-of-blogroll site-overview-item animated">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://paste.ubuntu.com/" title="https:&#x2F;&#x2F;paste.ubuntu.com&#x2F;" rel="noopener" target="_blank">Ubuntu Pastebin</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://send.firefox.com/" title="https:&#x2F;&#x2F;send.firefox.com&#x2F;" rel="noopener" target="_blank">Firefox Send</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://jkwzs.cn/" title="https:&#x2F;&#x2F;jkwzs.cn&#x2F;" rel="noopener" target="_blank">南花醉笔丶の个人博客</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://ywrby.cn/" title="https:&#x2F;&#x2F;ywrby.cn&#x2F;" rel="noopener" target="_blank">Ywrby个人博客</a>
        </li>
    </ul>
  </div>

        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://liukairui.me/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="Liu Kairui">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="LiuKairui Website">
      <meta itemprop="description" content="LiuKairui Persional Website">
    </span>
    
    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="JavaScript进阶版笔记 | LiuKairui Website">
      <meta itemprop="description" content="此版为JavaScript进阶版，以讲述原理为主,主讲:尚硅谷张晓飞,视频来自B站:BV14s411E7qf与BV1MJ41197Eu">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          JavaScript进阶版笔记
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2020-11-20 01:35:50" itemprop="dateCreated datePublished" datetime="2020-11-20T01:35:50+08:00">2020-11-20</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%89%8D%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">前端</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%89%8D%E7%AB%AF/JS/" itemprop="url" rel="index"><span itemprop="name">JS</span></a>
        </span>
    </span>

  
    <span id="/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/" class="post-meta-item leancloud_visitors" data-flag-title="JavaScript进阶版笔记" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="far fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
  
  <span class="post-meta-item">
    
    <span class="post-meta-item-icon">
      <i class="far fa-comment"></i>
    </span>
    <span class="post-meta-item-text">Valine：</span>
  
    <a title="valine" href="/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/" itemprop="commentCount"></span>
    </a>
  </span>
  
  

<script>
    CONFIG.hostname = location.hostname;
</script>
    <span class="post-meta-break"></span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>27k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>25 分钟</span>
    </span>
</div>

            <div class="post-description">此版为JavaScript进阶版，以讲述原理为主,主讲:尚硅谷张晓飞,视频来自B站:BV14s411E7qf与BV1MJ41197Eu</div>
        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <h2 id="数据类型">数据类型</h2>
<ul>
<li>分类
<ul>
<li>基本(值)类型
<ul>
<li>string: 任意字符串</li>
<li>number: 任意数字</li>
<li>boolean: true false</li>
<li>undefined: undefined</li>
<li>null: null</li>
</ul></li>
<li>对象(引用)类型
<ul>
<li>object: 任意对象</li>
<li>function: 一个特别的对象(可以执行)</li>
<li>array:
一种特别的对象(属性有数值下标属性,数组内部的元素是有序的)</li>
</ul></li>
</ul></li>
<li>判断
<ul>
<li>typeof:
返回数据类型的字符串表达<code>typeof tmp==="undefined"</code>,array和object的typeof都是object所以不能区别</li>
<li>instanceof: 实例</li>
<li>===/== 一般判断全等用===这个不做数据转化<code>a===undefined</code>
一般用于null undefined的判断(因为他们只有一个值)</li>
</ul></li>
<li>undefined与null区别
<ul>
<li>undefined 表示只有定义没有赋值</li>
<li>null 表示定义了赋值了值为null</li>
<li>设置null的初衷是为了表示这个变量准备被赋值成对象,但是目前还没有赋值,所以<code>typeof null</code>的结果是object</li>
<li>null的另一个作用是将没有用的对象的地址设置为null,当内存没人指的时候就会释放,被垃圾回收器回收</li>
</ul></li>
<li>在什么时候将变量的值赋值为null
<ul>
<li>在初始化但是临时不赋值的时候,为了标记</li>
<li>在变量不用的时候释放内存</li>
</ul></li>
<li>严格区分数据类型与变量类型
<ul>
<li>数据的类型
<ul>
<li>基本类型</li>
<li>对象类型</li>
</ul></li>
<li>变量类型(实际上指的是变量值的类型,是存了数字还是地址)
<ul>
<li>基本类型: 保存的是基本类型数据</li>
<li>引用类型: 保存的是地址的路径</li>
</ul></li>
</ul></li>
</ul>
<h2 id="数据变量与内存">数据,变量,与内存</h2>
<ul>
<li>数据:
存储在内存中代表特定信息的东西,本质上是<code>010101..</code></li>
<li>内存:
内存条通电之后可以存储数据的空间(临时的),一个内存块里面有两个小数据一个是地址值一个是存的值
<ul>
<li>内存的分类有栈,堆</li>
<li>栈里面存全局变量和局部变量</li>
<li>堆里面是对象的本身(但是表示堆的标识符是在堆空间里面的)</li>
</ul></li>
<li>变量: 可变换的量,由变量名和值组成,每个变量名都占用一小块内存</li>
</ul>
<p>内存中所有的操作的目标都是数据,操作的运算有:</p>
<ul>
<li>算数运算</li>
<li>逻辑运算</li>
<li>赋值运算</li>
<li>运行函数</li>
<li>数据,变量,内存之间的关系</li>
</ul>
<p>内存是存储数据的临时空间,变量是内存的标识</p>
<ul>
<li>内存与赋值的问题<br />
<code>var a=XXX;</code>a中到底存了什么?
<ul>
<li>当XXX是基本数据类型,那么他保存的就是这个数据</li>
<li>当XXX是对象的时候,保存的是对象的地址值</li>
<li>当XXX是变量的时候,保存的是XXX的内存内容(两者都有可能)</li>
<li>当两个引用变量指向了同一个对象,通过一个变量修改数据,那么另一个变量看到的是修改后的数据</li>
<li>对象在函数传递参数的时候是将内容赋值给了形参,对象赋值的内容是地址,所以相当于是传地址</li>
<li>值得注意这两种情况 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> a<span class="token operator">=</span><span class="token punctuation">&#123;</span><span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">12</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> b<span class="token operator">=</span>a<span class="token punctuation">;</span>
a<span class="token operator">=</span><span class="token punctuation">&#123;</span><span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">13</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
<span class="token comment">// 此时ab指向的地址发生了改变,两者不相干</span>
<span class="token keyword">var</span> <span class="token function-variable function">fun</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">v</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  v<span class="token operator">=</span><span class="token punctuation">&#123;</span><span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">15</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token function">fun</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 此时b并不会发生改变因为v是一个**独立的变量**,最开始是和b指向了一个地址,但是赋值之后指向的地址发生了改变,所以v的变化不会影响b</span></code></pre></li>
</ul></li>
<li>JS是如何管理内存的
<ol type="1">
<li>内存生命周期</li>
</ol>
<ul>
<li>分配小的内存空间,获得小内存的使用权</li>
<li>存储数据进行反复操作</li>
<li>没人指向小内存空间的时候释放空间</li>
</ul>
<ol start="2" type="1">
<li>释放内存</li>
</ol>
<ul>
<li>程序或者作用域结束的时候释放作用域里面的变量(注意这里指的是释放标识符,小内存早就被释放了)</li>
<li>对于对象使用垃圾回收器回收</li>
</ul></li>
</ul>
<h2 id="对象">对象</h2>
<ul>
<li>什么是对象
<ul>
<li>多个数据的封装体</li>
<li>用来保存多个数据的容器</li>
<li>一个对象代表现实中的一个事物</li>
</ul></li>
<li>为什么要用对象
<ul>
<li>统一管理多个元素</li>
</ul></li>
<li>对象的组成
<ul>
<li>属性</li>
<li>方法(特别的属性--属性值是函数)</li>
</ul></li>
<li>访问对象内部的元素
<ul>
<li><code>OBJ.属性名</code>
当属性名是关键字/包含<code>-</code>/包含<code></code>/变量名不确定,用变量存储变量名的时候不能用</li>
<li><code>OBJ["属性名"]</code></li>
</ul></li>
</ul>
<h2 id="函数">函数</h2>
<ul>
<li>为什么要用函数
<ul>
<li>提高代码复用</li>
</ul></li>
<li>如何定义函数
<ul>
<li>函数声明</li>
<li>表达式</li>
</ul></li>
<li>函数的调用
<ul>
<li><code>fun.call(obj)</code>:
让一个函数成为一个陌生属性的方法是JS的一大特性</li>
<li><code>AAA()</code></li>
</ul></li>
</ul>
<h2 id="回调函数">回调函数</h2>
<ul>
<li>什么是回调函数
<ul>
<li>自己定义的</li>
<li>自己没有调用(指的是没有写明,例如window.onclick就是一个没有调用的回调函数,是在特定时间自动执行的)</li>
<li>最后执行了</li>
</ul></li>
<li>常见的回调函数
<ul>
<li>dom事件回调函数(与用户交互比较重要的点,发生时间的DOM元素)</li>
<li>定时器回调函数</li>
<li>ajax回调函数(与后台交互比较重要的点)</li>
<li>生命周期回调函数</li>
</ul></li>
</ul>
<h2 id="iife">IIFE</h2>
<p>IIFE(Immediately-Invoked Function Expression) 立即调用函数表达式</p>
<p>一般来说我们写的是非匿名函数,这样可以将他存起来,当时我们也可以写没有对象接受内容的匿名函数,因为没有标识符标识他,所以他必须立即执行,否则以后就无法调用了(这里的非匿名不是说<code>setInterval(function()&#123;&#125;,1000)</code>这种,因为传值的时候相当于赋值了)</p>
<p>对于上述的匿名函数我们必须要当场执行 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"123"</span><span class="token punctuation">)</span>'
<span class="token punctuation">&#125;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
在后面加上<code>([参数列表])</code>就可以执行了,因为我们将前面当作了一个整体去执行,最好前面也加上一个<code>()</code>变成
<pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"123"</span><span class="token punctuation">)</span>'
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
加上<code>()</code>之后函数定义的变量就从之前的全局变量变成了局部变量,好处有:</p>
<ul>
<li>隐藏实现:这样的话其他函数就看不到这个函数了(因为本身他就要匿名,最好不要让其他函数看见)</li>
<li>不会污染外部的命名空间</li>
</ul>
<p>于是我们可以像C++中封装函数一样去封装一个JS函数 <pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">function</span> <span class="token function">work1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token comment">// true work code 1;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token keyword">function</span> <span class="token function">work2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token comment">// true work code 2;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token keyword">function</span> <span class="token function">work2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token comment">// true work code 3;</span>
  <span class="token punctuation">&#125;</span>
  window<span class="token punctuation">.</span><span class="token function-variable function">XXX</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">...</span>
      <span class="token keyword">return</span> <span class="token function">work1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">...</span>
      <span class="token keyword">return</span> <span class="token function">work2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">work3</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
我们希望实现一个模块,但是不想暴露细节函数,于是全员匿名,最后提供一个中控函数绑定到window,这在之后就是创建模块的方法,例如
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> myModule <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token function">module</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">var</span> someThing <span class="token operator">=</span> <span class="token string">"123"</span><span class="token punctuation">;</span>
  <span class="token keyword">var</span> otherThing <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token keyword">function</span> <span class="token function">doSomeThing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>someThing<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>

  <span class="token keyword">function</span> <span class="token function">doOtherThing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>otherThing<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>

  <span class="token keyword">return</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">doSomeThing</span><span class="token operator">:</span>doSomeThing<span class="token punctuation">,</span>
    <span class="token literal-property property">doOtherThing</span><span class="token operator">:</span>doOtherThing
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

myModule<span class="token punctuation">.</span><span class="token function">doSomeThing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
myModule<span class="token punctuation">.</span><span class="token function">doOtherThing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></p>
<h2 id="函数中的this">函数中的this</h2>
<p>注意的一点,对于如下的例子 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">fun1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">function</span> <span class="token function">fun2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">fun2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token function">fun1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
这里输出的this是<code>window</code>,同时请注意以下代码 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> tmp<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">fun1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">function</span> <span class="token function">fun2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">fun2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
tmp<span class="token punctuation">.</span>fun<span class="token operator">=</span>fun1<span class="token punctuation">;</span>
tmp<span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></p>
<p>返回 <pre class="language-none"><code class="language-none">&#123;fun: ƒ&#125;
VM144:5 Window &#123;0: Window, window: Window, self: Window, document: document, name: &quot;&quot;, location: Location, …&#125;</code></pre> 相当于只要不是明确是对象调的都是window</p>
<ul>
<li>this是什么
<ul>
<li><strong>任何函数本质上都是通过对象调用的</strong></li>
<li>所有函数内部都有一个变量this</li>
<li>他指向的是调用函数的当前对象</li>
</ul></li>
</ul>
<h2 id="js的分号问题">JS的分号问题</h2>
<ul>
<li>可加可不加</li>
<li>但是如果不加分号导致二义性要加(小中括号开头的),例如 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> a<span class="token operator">=</span><span class="token number">3</span>
<span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token operator">...</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
会被认为是要执行一个名字叫做<code>3</code>的函数,参数列表为fun...
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> a<span class="token operator">=</span><span class="token number">3</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token operator">...</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre> 那么就要加了</li>
<li>注意: JS在代码发布的时候会有一个<code>合理压缩</code>的过程,例如:
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> a<span class="token operator">=</span><span class="token number">123</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">my_first_function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token comment">// ohh here is a note</span>
  <span class="token keyword">return</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre> 会被压缩成 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> a<span class="token operator">=</span><span class="token number">123</span><span class="token punctuation">;</span><span class="token keyword">function</span> <span class="token function">b</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token keyword">return</span> <span class="token number">3</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span></code></pre> 不仅压行,还直接改函数名...</li>
</ul>
<h2 id="prototype">prototype</h2>
<p>任何<code>函数</code>都具有prototype属性,一个函数默认指向了一个Object空对象(原型对象),也就是说在函数被创建的时候会JS会默认创建一个对象,这个对象的内容是空的</p>
<p>原型对象的元素是给事例对象用的,</p>
<p>在<code>prototype</code>中还有一个元素是<code>constructor</code>这是一个引用变量,指向了指向prototype的对象,也就是构造函数与原型对象有一个相互引用的关系</p>
<h2 id="显式原型与隐式原型">显式原型与隐式原型</h2>
<ul>
<li>每个<strong>函数</strong>function都有一个<code>prototype</code>,也就是显式原型</li>
<li>每个<strong>事例对象</strong>都有一个<code>__proto__</code>,可以称为隐式原型</li>
<li>事例对象的<code>__proto__</code>的值是构造函数的<code>prototype</code></li>
<li><strong>注意</strong>:显式原型与隐式原型都是引用对象,指向的是原型,验证方法就是在创建元素后修改显式原型的内容</li>
<li>在ES6之前程序员可以直接操作显式原型,但是不能操作隐式原型</li>
</ul>
<p>与其他语言不同的是,大部分语言采用的是基于类的基础而JS是采用基于对象的继承,这就导致JS存在原型链</p>
<h2 id="原型链">原型链</h2>
<p>我们可以尝试一直输出一个对象的__porto__</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">Fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">var</span> FnFunctionVals<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> <span class="token number">666</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">var</span> fn<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Fn IS "</span><span class="token punctuation">,</span>fn<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Fn PROTO"</span><span class="token punctuation">,</span>fn<span class="token punctuation">.</span>__proto__<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Fn PROTO PROTO"</span><span class="token punctuation">,</span>fn<span class="token punctuation">.</span>__proto__<span class="token punctuation">.</span>__proto__<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Fn PROTO PROTO PROTO"</span><span class="token punctuation">,</span>fn<span class="token punctuation">.</span>__proto__<span class="token punctuation">.</span>__proto__<span class="token punctuation">.</span>__proto__<span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Fn IS "</span><span class="token punctuation">,</span>Fn<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Fn PROTO"</span><span class="token punctuation">,</span>Fn<span class="token punctuation">.</span>__proto__<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Fn PROTO PROTO"</span><span class="token punctuation">,</span>Fn<span class="token punctuation">.</span>__proto__<span class="token punctuation">.</span>__proto__<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Fn PROTO PROTO PROTO"</span><span class="token punctuation">,</span>Fn<span class="token punctuation">.</span>__proto__<span class="token punctuation">.</span>__proto__<span class="token punctuation">.</span>__proto__<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>结果 <pre class="language-js" data-language="js"><code class="language-js">Fn <span class="token constant">IS</span>  <span class="token literal-property property">Fn__proto__</span><span class="token operator">:</span> Object
Fn <span class="token constant">PROTO</span> <span class="token literal-property property">Objectconstructor</span><span class="token operator">:</span> ƒ <span class="token function">Fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>__proto__<span class="token operator">:</span> Object
Fn <span class="token constant">PROTO</span> <span class="token constant">PROTO</span> <span class="token literal-property property">Objectconstructor</span><span class="token operator">:</span> ƒ <span class="token function">Object</span><span class="token punctuation">(</span><span class="token punctuation">)</span>hasOwnProperty<span class="token operator">:</span> ƒ <span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token punctuation">)</span>isPrototypeOf<span class="token operator">:</span> ƒ <span class="token function">isPrototypeOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span>arguments<span class="token operator">:</span> <span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span>caller<span class="token operator">:</span> <span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span>length<span class="token operator">:</span> 1name<span class="token operator">:</span> <span class="token string">"isPrototypeOf"</span><span class="token literal-property property">__proto__</span><span class="token operator">:</span> <span class="token function">ƒ</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">[</span>Scopes<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token operator">:</span> Scopes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>propertyIsEnumerable<span class="token operator">:</span> ƒ <span class="token function">propertyIsEnumerable</span><span class="token punctuation">(</span><span class="token punctuation">)</span>toLocaleString<span class="token operator">:</span> ƒ <span class="token function">toLocaleString</span><span class="token punctuation">(</span><span class="token punctuation">)</span>toString<span class="token operator">:</span> ƒ <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span>valueOf<span class="token operator">:</span> ƒ <span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span>__defineGetter__<span class="token operator">:</span> ƒ <span class="token function">__defineGetter__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>__defineSetter__<span class="token operator">:</span> ƒ <span class="token function">__defineSetter__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>__lookupGetter__<span class="token operator">:</span> ƒ <span class="token function">__lookupGetter__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>__lookupSetter__<span class="token operator">:</span> ƒ <span class="token function">__lookupSetter__</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token keyword">get</span> <span class="token literal-property property">__proto__</span><span class="token operator">:</span> ƒ <span class="token function">__proto__</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token keyword">set</span> <span class="token literal-property property">__proto__</span><span class="token operator">:</span> ƒ <span class="token function">__proto__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
Fn <span class="token constant">PROTO</span> <span class="token constant">PROTO</span> <span class="token constant">PROTO</span> <span class="token keyword">null</span>
Fn <span class="token constant">IS</span>  ƒ <span class="token function">Fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        <span class="token keyword">var</span> FnFunctionVals<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">;</span>
        <span class="token keyword">function</span> <span class="token function">tmp</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
         <span class="token keyword">return</span> <span class="token number">666</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
Fn <span class="token constant">PROTO</span> <span class="token function">ƒ</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token punctuation">[</span>native code<span class="token punctuation">]</span> <span class="token punctuation">&#125;</span>
Fn <span class="token constant">PROTO</span> <span class="token constant">PROTO</span> <span class="token literal-property property">Objectconstructor</span><span class="token operator">:</span> ƒ <span class="token function">Object</span><span class="token punctuation">(</span><span class="token punctuation">)</span>hasOwnProperty<span class="token operator">:</span> ƒ <span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token punctuation">)</span>isPrototypeOf<span class="token operator">:</span> ƒ <span class="token function">isPrototypeOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span>propertyIsEnumerable<span class="token operator">:</span> ƒ <span class="token function">propertyIsEnumerable</span><span class="token punctuation">(</span><span class="token punctuation">)</span>toLocaleString<span class="token operator">:</span> ƒ <span class="token function">toLocaleString</span><span class="token punctuation">(</span><span class="token punctuation">)</span>toString<span class="token operator">:</span> ƒ <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span>valueOf<span class="token operator">:</span> ƒ <span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span>__defineGetter__<span class="token operator">:</span> ƒ <span class="token function">__defineGetter__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>__defineSetter__<span class="token operator">:</span> ƒ <span class="token function">__defineSetter__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>__lookupGetter__<span class="token operator">:</span> ƒ <span class="token function">__lookupGetter__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>__lookupSetter__<span class="token operator">:</span> ƒ <span class="token function">__lookupSetter__</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token keyword">get</span> <span class="token literal-property property">__proto__</span><span class="token operator">:</span> ƒ <span class="token function">__proto__</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token keyword">set</span> <span class="token literal-property property">__proto__</span><span class="token operator">:</span> ƒ <span class="token function">__proto__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
Fn <span class="token constant">PROTO</span> <span class="token constant">PROTO</span> <span class="token constant">PROTO</span> <span class="token keyword">null</span></code></pre>
可以看到是Fn这个<strong>对象</strong>,请注意,此处没有调用函数的prototype而是直接调用了对象的__proto__他们是一样的,可以看到fn对象的第一个原型就是Object,这个object包含了指回fn对象的<code>constructor</code>,之后这个对象又指向了一个Object对象,最后被指向的对象没有原型了,但是他还是一个Object对象,他包含了Object最基本的对象</p>
<pre class="mermaid">graph LR
    Fn[Fn函数标识符] --__proto__--> FnObj[Fn函数对象] --prototype--> Object[Object对象包含了函数中写在原型的函数] --__proto__--> ObjectNull[Object原型对象] --__proto__--> null[NULL空对象]
    Object --constructor--> FnObj
    JSObj[JS解释器的Object标识符] --__proto__--> objFun[JS解释器的Object函数对象] --__proto__--> ObjectNull[Object原型对象]
    fn[fn变量的标识符] --__proto__--> Fnme[Fn的实例对象此处有直接定义给fn的方法] --__proto__--> Object
    Object --constructor--> Fnme</pre>
<p>最后null的<code>__proto__</code>是报错...</p>
<p>从上面可以看到,我们其实是顺着隐式原型链连起来的,原型链是用来查找对象的属性的不是方法(虽然我认为方法也是属性...)</p>
<h2
id="构造函数原型等原型链之间的关系图与解释">构造函数,原型等原型链之间的关系图与解释</h2>
我们有构造函数<code>Foo()</code>
<pre class="mermaid">graph LR
  subgraph 实例
    f1[...=newFoo]
    o1[...=newObject]
  end
  subgraph 函数
    Foo[Function Foo]
    Obj[function Object]
    Fun[function Function]
  end
  subgraph 原型
    FooProt[Foo.prototype]
    ObjProt[Object.prototype]
    FunProt[Function.prototype]
  end
 f1 --__proto__-->FooProt
 Foo --prototypr-->FooProt
 FooProt--constructor-->Foo
 Foo --__proto__-->FunProt
 Fun --__proto__-->FunProt
 FunProt --constructor--> Fun
 Fun --prototype--> FunProt
 Obj --__proto__-->FunProt
 Obj --prototype--> ObjProt
 o1 --__proto__--> ObjProt
 FooProt--__proto__-->ObjProt
 ObjProt--__proto__--> NULL
 ObjProt--constructor--> Obj
 FunProt-->ObjProt</pre>
<p>从左上角开始看</p>
<ul>
<li>f1,f2是Foo构造函数构造的实例,他们的__proto__就是构造函数的prototype</li>
<li>对于构造函数Foo来说,prototype就是Foo的一个空实例,这个空实例的构造函数就是Foo</li>
<li>同时,Foo是一个函数,也是一个对象,Foo是由Function构造函数构造的一个function,所以Foo的__proto__是Function函数的prototype</li>
<li>对于构造函数Function来说他的prototype就是他的一个空实例,这个实例的构造函数就是他</li>
<li>同时Function是一个函数,所以Function是Function构造出来的一个对象,也具有__proto__,他的__proto__应该是Function函数的构造函数Function的prototype</li>
<li>对于Function的prototype来说,他是一个对象,所以他的__proto__就是Object</li>
<li>对于Object来说,他的prototype是他的空实例,空实例的构造函数就是Object</li>
<li>对于对象o1,他是Object的实例,所以__proto__就是Object的prototypr</li>
<li>对于Object来说,他是由Function创建的函数实例,所以他的__proto__就是Function的prototype</li>
</ul>
<h2 id="原型链的属性">原型链的属性</h2>
<p>我们可以把一个属性设置到原型链的属性上,那么我们声明一个事例的时候事例可以直接通过<code>.</code>访问到原型上设置的属性,当我们为这个实例设置相同的属性是时候,JS并不会查找原型链上有没有这个属性,而是直接将属性设置到了实例上,这相当于此时,对于这个实例有两个同名属性,一个在原型链上,一个在实例上,这样的修改不会影响到其他是实例</p>
<h2 id="执行上下文">执行上下文</h2>
<ul>
<li>代码的分类
<ul>
<li>全局代码</li>
<li>函数局部代码</li>
</ul></li>
<li>全局执行上下文
<ul>
<li>在执行全局代码前将window设置为全局执行上下文</li>
<li>对全局数据进行预处理
<ul>
<li>var定义为全局变量,值为undefined,添加windows属性</li>
<li>function 声明全局函数,同时赋值,添加为window方法</li>
<li>this设置为window</li>
</ul></li>
<li>从头执行代码</li>
</ul></li>
<li>函数执行上下文
<ul>
<li>在调用函数之前创建对应的函数执行上下文</li>
<li>对局部数据进行预处理
<ul>
<li>将形参列表赋值为实参为执行上下文添加对应的属性</li>
<li>将argument赋值,添加上下文属性</li>
<li>var定义局部变量,赋值为undefined,添加上下文属性</li>
<li>function声明函数,赋值函数内容,添加上下文方法</li>
<li>赋值this</li>
</ul></li>
<li>执行函数代码</li>
</ul></li>
<li>局部变量的栈
<ul>
<li>我们可以将存放标识符的栈进一步细分,存储全局变量的栈,存储局部函数变量的栈,全局元素栈可以被局部函数栈访问,但是局部元素栈的元素不可以在全局被访问,相当于这个栈在全局是被隐藏的</li>
</ul></li>
<li>执行上下文栈
<ul>
<li>全局代码执行的时候JS会创建一个栈存储全局上下文对象</li>
<li>执行window的时候压栈</li>
<li>函数执行的时候将函数上下文对象入栈</li>
<li>程序结束之后对象出栈</li>
<li>全局执行结束之后应该只可以看到window的上下文对象</li>
</ul></li>
</ul>
<h2 id="作用域与作用域链">作用域与作用域链</h2>
<ul>
<li>理解
<ul>
<li>就是一块地盘,一个代码所在的区域</li>
<li>相对于上下文对象,带编码的时候元素的作用域就确定了</li>
</ul></li>
<li>分类
<ul>
<li>全局作用域</li>
<li>函数作用域</li>
<li>块作用域(ES6之前没有)</li>
</ul></li>
<li>作用
<ul>
<li>隔离变量</li>
</ul></li>
<li>与执行上下文的区别
<ul>
<li>全局作用域外,每个函数都会创建自己的作用域,在函数定义的时候创建,而不是在函数调用的时候</li>
<li>全局执行上下文是字啊全局作用域确定,JS代码马上要执行的时候确定的</li>
<li>函数上下文是在调用函数的时候确定,函数体代码是在执行之前确定</li>
<li>作用域是静态的,函数定义好就一直存在,不会变化</li>
<li>上下文是动态的,调用的时候创建,结束的时候释放</li>
<li>上下文环境对象是从属于作用域的</li>
<li>全局上下文环境对应全局作用域</li>
<li>函数上下文环境对应函数作用域</li>
</ul></li>
<li>作用域链
<ul>
<li>嵌套的作用域形成的<strong>由内而外</strong>的链称为作用域链</li>
<li>当我们调用一个函数,JS顺着作用域链找不到就会报错,注意查找的时候如果这个属性是当前作用域中某个对象的属性,那么是找不到是</li>
</ul></li>
</ul>
<h2 id="循环变量监听">循环变量监听</h2>
<p>以前写过这样的代码 <pre class="language-js" data-language="js"><code class="language-js"><span class="token operator">&lt;</span><span class="token operator">!</span><span class="token constant">DOCTYPE</span> html<span class="token operator">></span>
<span class="token operator">&lt;</span>html lang<span class="token operator">=</span><span class="token string">"en"</span><span class="token operator">></span>
<span class="token operator">&lt;</span>head<span class="token operator">></span>
<span class="token operator">&lt;</span><span class="token operator">/</span>head<span class="token operator">></span>
<span class="token operator">&lt;</span>body<span class="token operator">></span>
    <span class="token operator">&lt;</span>button<span class="token operator">></span>我是第<span class="token number">0</span>个<span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">></span>
    <span class="token operator">&lt;</span>button<span class="token operator">></span>我是第<span class="token number">1</span>个<span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">></span>
    <span class="token operator">&lt;</span>button<span class="token operator">></span>我是第<span class="token number">2</span>个<span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">></span>
<span class="token operator">&lt;</span><span class="token operator">/</span>body<span class="token operator">></span>

<span class="token operator">&lt;</span>script<span class="token operator">></span>
    window<span class="token punctuation">.</span><span class="token function-variable function">onload</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        <span class="token keyword">var</span> bts<span class="token operator">=</span>document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">var</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span>len<span class="token operator">=</span>bts<span class="token punctuation">.</span>length<span class="token punctuation">;</span>i<span class="token operator">&lt;</span>len<span class="token punctuation">;</span>i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
            bts<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>idx<span class="token operator">=</span>i<span class="token punctuation">;</span>
            bts<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function-variable function">onclick</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                <span class="token function">alert</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>idx<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>script<span class="token operator">></span>
<span class="token operator">&lt;</span><span class="token operator">/</span>html<span class="token operator">></span></code></pre> 实现了点击第几个弹出几</p>
<p>有一个坑就是如果不记录这个按钮是第几个就会出现谁点击都是3,这是因为在循环的时候只进行了函数声明,调用的时候函数内部i去window的作用域下找i,只找到循环结束的3,这就导致全输出3,一个解决方法是为按钮附上index值,也可以添加一个作用域不让onclick出去找i
<pre class="language-js" data-language="js"><code class="language-js">window<span class="token punctuation">.</span><span class="token function-variable function">onload</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">var</span> bts<span class="token operator">=</span>document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">var</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span>len<span class="token operator">=</span>bts<span class="token punctuation">.</span>length<span class="token punctuation">;</span>i<span class="token operator">&lt;</span>bts<span class="token punctuation">.</span>length<span class="token punctuation">;</span>i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        <span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">i</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
            <span class="token keyword">var</span> sigBtn<span class="token operator">=</span>bts<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
            sigBtn<span class="token punctuation">.</span><span class="token function-variable function">onclick</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
                <span class="token function">alert</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre>
区别就是为window内部又写了一个作用域,形参为i,这样的话找i就一定找的是形参i,现在只需要告诉每个按钮i的具体值,可以使用函数调用传递参数,但是这个函数只是在这里用一下,所以完全可以匿名立即执行,于是有了上面的代码,注意匿名函数的函数作用域,实际上这就用到了闭包的技术</p>
<h2 id="闭包">闭包</h2>
<ul>
<li>如何产生闭包
<ul>
<li>当一个嵌套的内部函数引用了嵌套的外部函数的变量,就产生了闭包</li>
</ul></li>
<li>闭包是什么
<ul>
<li>闭包有2种理解</li>
<li>一种认为是嵌套在内部的子函数</li>
<li>一种认为是包含被引用变量的对象</li>
<li>他存在与内部函数中</li>
</ul></li>
<li>产生闭包的条件
<ul>
<li>函数嵌套</li>
<li>内部函数引用了外部函数的变量</li>
<li>外部函数被调用(注意,闭包出现于外层函数执行子函数变量提升的时候,而不是子函数被调用,甚至可能子函数不会被调用,但是在变量提升的时候已经有了闭包,当然,如果写的是<code>var tmp=function()&#123;&#125;</code>那必然在父函数开始的时候不产生闭包)</li>
</ul></li>
</ul>
<p>陷阱 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">fn1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">var</span> a<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">;</span>
    <span class="token keyword">function</span> <span class="token function">fn2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        a<span class="token operator">++</span><span class="token punctuation">;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> fn2<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">var</span> f<span class="token operator">=</span><span class="token function">fn1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre> 输出分别是3 4</p>
<p>看到f定义的那一句,模拟执行,f获得了fn1的返回值,我们执行fn1,首先是进入fn1,创建闭包,<strong>把闭包给了fn2</strong>,不调用fn2,直接返回fn2<strong>对象,不仅仅是代码,连着fn2刚刚拿到的闭包一起返回了</strong>,调用f的时候fn2使用了自己的闭包,找到a=2,输出了3,再次调用的时候fn2使用了自己的闭包,找到a=3,输出了4,想要恢复很简单,重新赋值f</p>
<p>其实错误版本的按钮点击函数,也是由于闭包惹得祸,如果没有闭包,函数已经被赋值怎么可能找到外边还有一个i呢,也是在定义的时候已经把i传进了onclick函数</p>
<ul>
<li><p>chrome开发人员工具<code>Call Stack</code>
类似于上下文栈,唯一特殊的(anonymous)指的是全局栈</p></li>
<li><p>闭包的作用</p></li>
<li><p>使函数内部的变量在函数执行结束之后仍然活在内存中</p></li>
<li><p>让外部函数可以直接操作其他作用域的局部变量</p></li>
<li><p>被闭包指向的局部变量在函数执行完后不消失的原因是有闭包在指向这个变量,
而闭包没有消失的原因是有元素指向的存储闭包的函数</p></li>
<li><p>闭包的生命周期</p>
<ul>
<li>在子函数被定义的时候产生</li>
<li>在子函数成为垃圾对象的时候消失</li>
</ul></li>
</ul>
<h2 id="利用闭包实现js模块">利用闭包实现js模块</h2>
<ul>
<li>js模块就是具有特定功能的js文件,要求如下</li>
<li>将所有的函数与功能都放在函数内部</li>
<li>函数只可以暴露一个或者多个方法</li>
<li>当我们想要返回多个方法的时候可以采用对象的方法直接封装所有的函数,属性名可以命名为方法名,更加方便</li>
</ul>
<p>例如: <pre class="language-html" data-language="html"><code class="language-html"><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span>Document<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>./js/myScript.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript">
    <span class="token keyword">var</span> fn <span class="token operator">=</span> <span class="token function">myModule</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    fn<span class="token punctuation">.</span><span class="token function">dootherthing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">></span></span></code></pre> <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">myModule</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">var</span> msg<span class="token operator">=</span><span class="token string">"My atguigu"</span><span class="token punctuation">;</span>
    <span class="token keyword">function</span> <span class="token function">dosomething</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"dosomtthing() "</span><span class="token operator">+</span>msg<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">function</span> <span class="token function">dootherthing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"dootherthing() "</span><span class="token operator">+</span>msg<span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">dosomething</span><span class="token operator">:</span> dosomething<span class="token punctuation">,</span>
        <span class="token literal-property property">dootherthing</span><span class="token operator">:</span> dootherthing
    <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p>也可以使用立即调用函数直接将事例写入到window中 <pre class="language-html" data-language="html"><code class="language-html"><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span>Document<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>./js/myScript.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript">
    fn<span class="token punctuation">.</span><span class="token function">dootherthing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">></span></span></code></pre>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">var</span> msg<span class="token operator">=</span><span class="token string">"My atguigu"</span><span class="token punctuation">;</span>
    <span class="token keyword">function</span> <span class="token function">dosomething</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"dosomtthing() "</span><span class="token operator">+</span>msg<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">function</span> <span class="token function">dootherthing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"dootherthing() "</span><span class="token operator">+</span>msg<span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    window<span class="token punctuation">.</span>fn<span class="token operator">=</span><span class="token punctuation">&#123;</span>
        <span class="token literal-property property">dosomething</span><span class="token operator">:</span>dosomething<span class="token punctuation">,</span>
        <span class="token literal-property property">dootherthing</span><span class="token operator">:</span>dootherthing
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></p>
<ul>
<li>闭包的缺点
<ul>
<li>局部变量释放延迟,占用内存</li>
<li>容易造成内存泄漏</li>
</ul></li>
<li>解决方案
<ul>
<li>及时释放(<code>f=null</code>使得内部函数成为垃圾对象)</li>
<li>不用闭包</li>
</ul></li>
</ul>
<h2 id="内存溢出与泄漏">内存溢出与泄漏</h2>
<ul>
<li>内存溢出
<ul>
<li>一种程序运行的时候出现的错误</li>
<li>当程序运行的时候需要内存超过剩余内存的时候,会抛出内存溢出错误
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> obj<span class="token operator">=</span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">var</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span><span class="token operator">&lt;</span><span class="token number">10000</span><span class="token punctuation">;</span>i<span class="token operator">++</span><span class="token punctuation">)</span>
  obj<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Array</span><span class="token punctuation">(</span><span class="token number">10000000</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
会造成溢出(同时注意这种语法,obj是一个伪数组,其实就是obj下面的属性为0,1,2,3...)浏览器显示崩溃了,内存不足</li>
</ul></li>
<li>内存泄漏
<ul>
<li>占用的内存没有被及时释放,这不是错误,只是一种问题,累计的内存泄漏多了容易导致内存溢出</li>
<li>原因
<ul>
<li>错误的调用了全局变量(eg 没有写var)</li>
<li>没有及时清理计时器或回调函数</li>
<li>闭包</li>
</ul></li>
</ul></li>
</ul>
<h2 id="对象的创建模式">对象的创建模式</h2>
<ul>
<li>Object构造函数模式
<ul>
<li>先创建一个空的object对象,然后动态的添加属性/方法</li>
<li>起始的时候对象内部的数据不确定</li>
<li>问题:语句多 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
p<span class="token punctuation">.</span>name<span class="token operator">=</span><span class="token string">"1"</span><span class="token punctuation">;</span>
p<span class="token punctuation">.</span>age<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">;</span>
p<span class="token punctuation">.</span><span class="token function-variable function">setName</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span> 
<span class="token punctuation">&#125;</span></code></pre></li>
</ul></li>
<li>对象字面量模式
<ul>
<li>使用<code>&#123;&#125;</code>创建对象,同时指定属性/方法</li>
<li>适用于起始对象内部的元素数据是确定的</li>
<li>问题: 如果创建了多个对象会有重复代码 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> p<span class="token operator">=</span><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">"tom"</span><span class="token punctuation">,</span>
  <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">12</span><span class="token punctuation">,</span>
  <span class="token function-variable function">setname</span><span class="token operator">:</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
</ul></li>
<li>工厂模式
<ul>
<li>通过工厂函数(返回对象的函数)创建对象然后返回</li>
<li>适用场景: 需要创建多个函数</li>
<li>问题: 没有一个对象有具体的类型,都是Object <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">makePeople</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span>age</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">var</span> p<span class="token operator">=</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">"tom"</span><span class="token punctuation">,</span>
    <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">12</span><span class="token punctuation">,</span>
    <span class="token function-variable function">setname</span><span class="token operator">:</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token keyword">return</span> p<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
</ul></li>
<li>自定义构造函数模式
<ul>
<li>自定义构造函数,通过new创建对象</li>
<li>适用场景: 需要创建多个类确定的对象</li>
<li>问题: 每个对象都有相同的数据 占用内存 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">People</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span>age</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age<span class="token operator">=</span>age<span class="token punctuation">;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">setname</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre>
对于每一个事例,属性可能不相同,内存相互独立,但是方法是一样的,但是内存还是独立的,这造成了内存的占用,所以要将函数放在原型上,这样所有的函数都指向同一个"空对象"于是有了下面的模式</li>
</ul></li>
<li>构造函数+原型的组合模式
<ul>
<li>自定义构造函数,属性在函数中初始化,方法添加到原型上</li>
<li>适用于要创建多个类型创建的对象 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">People</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span>age</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age<span class="token operator">=</span>age<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token class-name">Person</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">setname</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
</ul></li>
</ul>
<h2 id="继承模式-原型链的继承">继承模式: 原型链的继承</h2>
<p>当创建了两个对象的构造-原型函数之后,需要建立两个类的继承关系,但是js是基于对象的继承的,所以子元素需要继承父元素的原型链,只需要将子元素<strong>构造函数</strong>的prototype设置为父元素的<strong>实例</strong>,eg
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">Supper</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>supProp<span class="token operator">=</span><span class="token string">"root"</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token class-name">Supper</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">showSupper</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token function">alert</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>supProp<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">Suber</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>subProp<span class="token operator">=</span><span class="token string">"suber"</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token class-name">Suber</span><span class="token punctuation">.</span>prototype<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Supper</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>     <span class="token comment">// 注意这里要先写,否则之前写的就成垃圾了</span>

<span class="token class-name">Suber</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">showSuber</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token function">alert</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>subProp<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">var</span> sub<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Suber</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
sub<span class="token punctuation">.</span><span class="token function">showSupper</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
sub<span class="token punctuation">.</span><span class="token function">showSuber</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
注意,以上代码存在隐患,因为sub是sup的子元素所以把Sub的prototype设置为Sub的实例,但是Sup实例的构造函数还是Sup,这里要同意修正为sub
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">Supper</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>supProp<span class="token operator">=</span><span class="token string">"root"</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token class-name">Supper</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">showSupper</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token function">alert</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>supProp<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">Suber</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>subProp<span class="token operator">=</span><span class="token string">"suber"</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token class-name">Suber</span><span class="token punctuation">.</span>prototype<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Supper</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>     <span class="token comment">// 注意这里要先写,否则之前写的就成垃圾了</span>
<span class="token class-name">Suber</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> Suber<span class="token punctuation">;</span>

<span class="token class-name">Suber</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">showSuber</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token function">alert</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>subProp<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">var</span> sub<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Suber</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
sub<span class="token punctuation">.</span><span class="token function">showSupper</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
sub<span class="token punctuation">.</span><span class="token function">showSuber</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></p>
<h2 id="继承模式借用构造函数继承">继承模式:借用构造函数继承</h2>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">Person</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span>age</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age<span class="token operator">=</span>age<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">function</span> <span class="token function">Student</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span>age<span class="token punctuation">,</span>p</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token function">Person</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span>name<span class="token punctuation">,</span>age<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>p<span class="token operator">=</span>p<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>相当于是 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">Student</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span>age<span class="token punctuation">,</span>p</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age<span class="token operator">=</span>age<span class="token punctuation">;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>p<span class="token operator">=</span>p<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre> 并没有创建出一个继承关系,但是能用</p>
<h2 id="继承模式-组合继承">继承模式: 组合继承</h2>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">Person</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span>age</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age<span class="token operator">=</span>age<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token class-name">Person</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">setname</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">=</span>name<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">Student</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span>age<span class="token punctuation">,</span>p</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token function">Person</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span>name<span class="token punctuation">,</span>age<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>p<span class="token operator">=</span>p<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token class-name">Student</span><span class="token punctuation">.</span>prototype<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Student</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor<span class="token operator">=</span>Student<span class="token punctuation">;</span>
<span class="token class-name">Student</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">setp</span><span class="token operator">=</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">p</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>p<span class="token operator">=</span>p<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">var</span> s<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Student</span><span class="token punctuation">(</span><span class="token string">"A"</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">setname</span><span class="token punctuation">(</span><span class="token string">"B"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">setp</span><span class="token punctuation">(</span><span class="token number">123</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="复习">复习</h2>
<p>白天看</p>
<h2 id="进程与线程">进程与线程</h2>
<ul>
<li>进程: 程序的一次允许占用了一个独立的内存空间</li>
<li>线程:
进程内部一个独立的执行单元,是程序执行的一个完整流程,是CPU最小调度单元</li>
<li>一个程序可以创建多个进程</li>
<li>一个程序如果每个<strong>进程只有一个线程</strong>那么就叫他但线程的</li>
<li>应用必须运行在一个进程的线程上</li>
<li>一个进程至少有一个允许的线程,叫主线程,自动创建,其他的叫分线程</li>
<li>一个进程的数据何以供多线程共享,进程之间不共享</li>
<li>线程池保存了多个线程对象容器实现复用</li>
<li>多个线程不一定同时进行,例如线程数目大于cpu核心数目</li>
</ul>
<p>比较:</p>
<ul>
<li>多线程
<ul>
<li>优点:提高CPU利用率</li>
<li>缺点:创建多线程有开心,线程切换有开销,存在锁死与状态同步问题</li>
</ul></li>
<li>单线程
<ul>
<li>优点: 代码简单</li>
<li>缺点: 慢</li>
</ul></li>
<li>JS是单线程运行的,但是可以使用H5的web workers进行多线程允许</li>
<li>浏览器是多线程允许的</li>
<li>浏览器有单进程的,有多进程的
<ul>
<li>多进程: chrome 新IE</li>
<li>单进行: 火狐 老IE</li>
</ul></li>
</ul>
<h2 id="浏览器内核">浏览器内核</h2>
<p>浏览器内核: 支持浏览器允许的核心程序</p>
<ul>
<li>chrome/Safasi: webkit</li>
<li>firefox : Gecko</li>
<li>IE : trident</li>
</ul>
<blockquote>
<p>页面的绘制（绘制，就是把一个HTML文件变成一个活灵活现的页面展示的过程...），只有一半轮子是Chrome自己做的，还有一部分来自于WebKit，这个Apple打造的Web渲染器。。。
之所以说是一半轮子来源于WebKit，是因为WebKit本身包含两部分主要内容，一部分是做Html渲染的，另一部分是做JavaScript解析的。在Chrome中，只有Html的渲染采用了WebKit的代码，而在JavaScript上，重新搭建了一个NB哄哄的V8引擎。目标是，用WebKit
+
V8的强强联手，打造一款上网冲浪的法拉利，从效果来看，还着实做的不错。。。
不过，虽说Chrome和WebKit都是开源的，并联手工作。但是，Chrome还是刻意的和WebKit保持了距离，为其始乱终弃埋下了伏笔。Chrome在WebKit上封装了一层，称为WebKit
Glue。Glue层中，大部分类型的结构和接口都和WebKit类似，Chrome中依托WebKit的组件，都只是调用WebKit
Glue层的接口，而不是直接调用WebKit中的类型。按照Chrome自己文档中的话来说，就是，虽然我们再用WebKit实现页面的渲染，但通过这个设计（加一个间接层...）已经从某种程度大大降低了与WebKit的耦合，使得可以很容易将WebKit换成某个未来可能出现的更好的渲染引擎。。。</p>
</blockquote>
<p>内核是一个大程序,有很多模块</p>
<ul>
<li>主线程
<ul>
<li>JS引擎:解析运行JS</li>
<li>HTML,CSS文档解析模块: 负责解析文本文件</li>
<li>DOM/CSS模块: 负责DOM文档结构对象的构建</li>
<li>布局与渲染模块: 负责布局效果的绘制</li>
</ul></li>
<li>分线程
<ul>
<li>定时器模块:
JS代码是单线程的,所以虽然模块是在分线程,但是代码还是在主线程</li>
<li>DOM事件响应模块</li>
<li>网络请求模块</li>
<li>...</li>
</ul></li>
</ul>
<h2 id="关于定时器">关于定时器</h2>
<p>定时器真的是定时执行的吗?</p>
<p>定时器一般会延迟一点点(可以接受),单也有可能会延长很多时间(例如在支持很大的循环)</p>
<h2 id="验证js是单线程执行的">验证JS是单线程执行的</h2>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"A"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"B"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"000000"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">"pause"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"111111"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>当点击确定后等一会儿才开始alert,说明alert同时暂停了定时器模块与主线程,但是最新的chrome修改了定时器框架,不用等待了,按顺序输出</p>
<h2 id="事件循环模型">事件循环模型</h2>
<ul>
<li>代码分类:
<ul>
<li>初始化代码</li>
<li>回调代码</li>
</ul></li>
<li>js引擎的执行流程
<ul>
<li>执行初始化函数代码,有一部分代码会在所有代码执行完才运行
我们称之为异步调用<br />
</li>
<li>设置计时器,监听,网络请求</li>
<li>在DOM事件发生的时候调用回调函数</li>
</ul></li>
<li>模型的2个重要组成部分:
<ul>
<li>事件管理模块</li>
<li>回调队列</li>
</ul></li>
<li>模型的运转流程
<ul>
<li>执行初始化代码, 将事件回调函数交给对应模块管理</li>
<li>当事件发生时, 管理模块会将回调函数及其数据添加到回调列队中</li>
<li>只有当初始化代码执行完后(可能要一定时间),
才会遍历读取回调队列中的回调函数执行</li>
</ul></li>
</ul>
<h2 id="h5-web-workers">H5 Web Workers</h2>
<ul>
<li>可以让js在分线程执行</li>
<li>Worker <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> worker <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Worker</span><span class="token punctuation">(</span><span class="token string">'worker.js'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
worker<span class="token punctuation">.</span><span class="token function-variable function">onMessage</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>event<span class="token punctuation">.</span>data<span class="token punctuation">&#125;</span> <span class="token operator">:</span> 用来接收另一个线程发送过来的数据的回调
worker<span class="token punctuation">.</span><span class="token function">postMessage</span><span class="token punctuation">(</span>data1<span class="token punctuation">)</span> <span class="token operator">:</span> 向另一个线程发送数据</code></pre></li>
<li>问题:
<ul>
<li>worker内代码不能操作DOM更新UI</li>
<li>不是每个浏览器都支持这个新特性</li>
<li>不能跨域加载JS</li>
</ul></li>
</ul>
<h2 id="promise">Promise</h2>
<h3 id="js语法准备">JS语法准备</h3>
<h4 id="实例对象与函数对象">实例对象与函数对象</h4>
<ul>
<li>实例对象是<code>new</code>创建出来的对象</li>
<li>函数对象是将函数作为对象使用</li>
</ul>
<p><strong>注意区分函数与对象</strong></p>
<ul>
<li><code>.</code>左边的是对象, 例如:
<code>X.Y.prototype</code>中的<code>X.Y</code></li>
<li><code>()</code>左边的是函数, 例如:
<code>X().Y()()</code>中的<code>X().Y()</code>, X的返回值是一个对象,
这个对象有Y函数, Y函数的返回值还是一个函数</li>
<li><code>()</code>整体的是返回值, 例如:
<code>X().Y()()</code>中的<code>X().Y()()</code></li>
</ul>
<p>当一个函数Fn既体现函数的作用(调用了<code>Fn()</code>),
又体现了对象的作用<code>Fn.xx</code>, 我们说Fn是函数对象</p>
<h4 id="函数的callapplybind方法">函数的call/apply/bind方法</h4>
<p>首先这三个参数都是用于改变this的指向 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">'张三'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">18</span><span class="token punctuation">,</span>
    <span class="token function-variable function">func</span><span class="token operator">:</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">+</span> <span class="token string">"年龄"</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>age<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> obj2 <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">'李四'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">20</span>
<span class="token punctuation">&#125;</span>
obj<span class="token punctuation">.</span><span class="token function">func</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>obj2<span class="token punctuation">)</span> <span class="token comment">//李四年龄20</span>
obj<span class="token punctuation">.</span><span class="token function">func</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>obj2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//李四年龄20</span>
obj<span class="token punctuation">.</span><span class="token function">func</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>obj2<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//李四年龄20</span></code></pre> 这三个结果都一样,
bind后面多一个括号是因为
bind返回值是一个函数加上（）编程立即执行函数</p>
<p><strong>Call</strong></p>
<p>用法：<code>Object.call(obj,arg1,arg2.......)</code></p>
<p>参数：</p>
<ul>
<li>第一个参数obj是作为函数上下文的对象(也就是this)</li>
<li>第二个参数arg1：从第二个参数开始后续所有参数都是传给方法的参数</li>
</ul>
<p>示例 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">'张三'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">18</span><span class="token punctuation">,</span>
    <span class="token function-variable function">func</span><span class="token operator">:</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">job<span class="token punctuation">,</span>sal</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">+</span> <span class="token string">"年龄"</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">+</span><span class="token string">"工作："</span><span class="token operator">+</span>job <span class="token operator">+</span> <span class="token string">"   sal:"</span><span class="token operator">+</span>sal<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> obj2 <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">'李四'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">20</span>
<span class="token punctuation">&#125;</span>
obj<span class="token punctuation">.</span><span class="token function">func</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>obj2<span class="token punctuation">,</span><span class="token string">'Programer'</span><span class="token punctuation">,</span><span class="token number">5000</span><span class="token punctuation">)</span> <span class="token comment">//李四年龄20工作：Programer   sal:5000</span></code></pre></p>
<p><strong>apply</strong></p>
<p>用法：<code>Object.apply(obj,[args])</code></p>
<p>参数：</p>
<ul>
<li>第一个参数obj是作为函数上下文的对象(也就是this)</li>
<li>第二个参数args:是一个数组作为参数传入 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">'张三'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">18</span><span class="token punctuation">,</span>
    <span class="token function-variable function">func</span><span class="token operator">:</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">job<span class="token punctuation">,</span>sal</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">+</span> <span class="token string">"年龄"</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">+</span><span class="token string">"工作："</span><span class="token operator">+</span>job <span class="token operator">+</span> <span class="token string">"   sal:"</span><span class="token operator">+</span>sal<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> obj2 <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">'李四'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">20</span>
<span class="token punctuation">&#125;</span>
obj<span class="token punctuation">.</span><span class="token function">func</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>obj2<span class="token punctuation">,</span><span class="token string">'Programer'</span><span class="token punctuation">,</span><span class="token number">5000</span><span class="token punctuation">)</span> <span class="token comment">//李四年龄20工作：Programer   sal:5000</span>
obj<span class="token punctuation">.</span><span class="token function">func</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>obj2<span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token string">'Programer'</span><span class="token punctuation">,</span><span class="token number">5000</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//李四年龄20工作：Programer   sal:5000</span></code></pre>
<strong>bind</strong></li>
</ul>
<p>用法：<code>Object.bind(obj,arg1,arg2.......)</code></p>
<p>参数：</p>
<ul>
<li>第一个参数obj是作为函数上下文的对象(也就是this)</li>
<li>第二个参数arg1：从第二个参数开始后续所有参数都是传给方法的 参数</li>
</ul>
<p>并且返回值是一个function <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">'张三'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">18</span><span class="token punctuation">,</span>
    <span class="token function-variable function">func</span><span class="token operator">:</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">job<span class="token punctuation">,</span>sal</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">+</span> <span class="token string">"年龄"</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">+</span><span class="token string">"工作："</span><span class="token operator">+</span>job <span class="token operator">+</span> <span class="token string">"   sal:"</span><span class="token operator">+</span>sal<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> obj2 <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span><span class="token string">'李四'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">age</span><span class="token operator">:</span><span class="token number">20</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> newFunc <span class="token operator">=</span>obj<span class="token punctuation">.</span><span class="token function">func</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>obj2<span class="token punctuation">,</span><span class="token string">'Programer'</span><span class="token punctuation">,</span><span class="token number">5000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> newFunc<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//function</span>
<span class="token function">newFunc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//李四年龄20工作：Programer   sal:5000</span></code></pre> <strong>总结</strong></p>
<ul>
<li>call和apply的区别：两个函数都是改变函数执行上下文的，但是传的参数不同</li>
<li>bind和其他两个差别在：传参与call相同，但是bind会返回一个新的函数</li>
</ul>
<h4 id="两种类型的回调函数">两种类型的回调函数</h4>
<p><strong>回调函数</strong></p>
<ul>
<li>是我自己定义的</li>
<li>我没有亲自去调用这个函数</li>
<li>但是他最后执行了</li>
</ul>
<p><strong>同步回调函数</strong></p>
<p>考虑代码 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
arr<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">t</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">dir</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"END"</span><span class="token punctuation">)</span></code></pre> 按照异步的思想, 队列中应该是: forEach() &lt;-
console.log() &lt;- console.log(1...3)</p>
<p>但是执行的时候我们看到的是: <code>1 2 3 END</code></p>
<p>这是因为forEach中的这个回调函数是<strong>同步回调函数</strong>,
这种函数会立即执行, 执行完才执行后面的函数,
JS不会将这类函数放在回调队列中</p>
<p><strong>异步回调函数</strong></p>
<p>与之对应, 回调函数不会立即执行, 会放在回调队列中将来再执行,
例如<code>setTimeout(回调,t)</code></p>
<h4 id="错误处理">错误处理</h4>
<p>JS的错误是一个对象模型, 有几种内置错误</p>
<ul>
<li>Error: 所有错误的父类</li>
<li>ReferenceError: 引用错误, 引用了不寻在的变量 <pre class="language-js" data-language="js"><code class="language-js">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span>
<span class="token comment">// ReferenceError: a is not defined</span></code></pre></li>
<li>TypeError: 数据类型不正确 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> a <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">.</span>__proto__<span class="token punctuation">)</span>
<span class="token comment">// TypeError: Cannot read property '__proto__' of null</span></code></pre></li>
<li>RangeError: 数据值超出允许范围, 一般指的是爆栈,
不是数字过大或者访问越界 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// RangeError: Maximum call stack size exceeded</span>
<span class="token keyword">let</span> t <span class="token operator">=</span> Number<span class="token punctuation">.</span><span class="token constant">MAX_VALUE</span><span class="token operator">*</span><span class="token number">2</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Infinity</span>
<span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// undefined</span></code></pre></li>
<li>SyntaxError: 语法错误</li>
</ul>
<p>遇到错误需要进行处理, 相关的语句有 - <code>try-catch</code>捕获错误
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> t<span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>t<span class="token punctuation">.</span>pro<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span> <span class="token keyword">catch</span><span class="token punctuation">(</span>Error<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"ERROR:"</span><span class="token punctuation">,</span>Error<span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"END"</span><span class="token punctuation">)</span>
<span class="token comment">// ERROR: TypeError: Cannot read property 'pro' of undefined</span>
<span class="token comment">//     at Object.&lt;anonymous> (/home/liukairui/CODE/CodeSnippet/Promise/demo1/index.js:3:19)</span>
<span class="token comment">//     at Module._compile (node:internal/modules/cjs/loader:1101:14)</span>
<span class="token comment">//     at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)</span>
<span class="token comment">//     at Module.load (node:internal/modules/cjs/loader:981:32)</span>
<span class="token comment">//     at Function.Module._load (node:internal/modules/cjs/loader:822:12)</span>
<span class="token comment">//     at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12)</span>
<span class="token comment">//     at node:internal/main/run_main_module:17:47</span>
<span class="token comment">// END</span></code></pre> 这里的Error是一个对象,
打印的时候打印出好几行(依靠toString),可以查看Error的结构 <pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">TypeError</span><span class="token operator">:</span> Cannot read properties <span class="token keyword">of</span> <span class="token keyword">undefined</span> <span class="token punctuation">(</span>reading <span class="token string">'pro'</span><span class="token punctuation">)</span>
    at <span class="token operator">&lt;</span>anonymous<span class="token operator">></span><span class="token operator">:</span><span class="token number">3</span><span class="token operator">:</span><span class="token number">19</span>
<span class="token literal-property property">message</span><span class="token operator">:</span> <span class="token string">"Cannot read properties of undefined (reading 'pro')"</span>
<span class="token literal-property property">stack</span><span class="token operator">:</span> <span class="token string">"TypeError: Cannot read properties of undefined (reading 'pro')\n    at &lt;anonymous>:3:19"</span>
<span class="token punctuation">[</span><span class="token punctuation">[</span>Prototype<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token operator">:</span> Error</code></pre>
Error是一个TypeError类对象, 有message(错误信息)与stack(调用栈)属性,
父类是Error - <code>throw error</code>抛出自定义的错误 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">doRand</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">let</span> t <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span>t<span class="token operator">&lt;</span><span class="token number">0.5</span><span class="token punctuation">)</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Pass"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">else</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">"Opp"</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">while</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">try</span><span class="token punctuation">&#123;</span>
    <span class="token function">doRand</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token keyword">catch</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Some Error"</span><span class="token punctuation">,</span>e<span class="token punctuation">.</span>message<span class="token punctuation">)</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre>
一般自己抛出自定义错误的时候使用Error类而不是用内置类,
这样的话错误就会抛出给函数的调用者</p>
<h3 id="promise的使用">Promise的使用</h3>
<h4 id="是什么">是什么</h4>
<p><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">MDN链接</a></p>
<p>Promise是承诺, 承诺将来会给你一个数据,
数据可能是成功的也可能是失败的</p>
<ul>
<li>Promise是JS进行异步编程的<strong>新的</strong>解决方案(在Promise之前我们使用回调函数进行)</li>
<li>从语法上说Promise是一个<strong>构造</strong>函数(Promise的实例去实现功能)</li>
<li>从功能上话Promise对象用来封装一个异步操作, 并获取结果</li>
</ul>
<p><strong>Promise的状态</strong></p>
<p>Promise被new出来的时候处于pading状态,
之后可以转换为resolved(成功)状态或者rejected(失败)状态,
无论转换为哪一个都不会变化了,
一般将成功结果的数据称为value并执行onResolved(),
将失败结果的数据称为reason/error并执行onRejected()最后得到一个新的Promise</p>
<p><strong>Promise的回调函数</strong></p>
<p>Promise的<strong>执行器函数</strong>是同步回调函数,
一旦Promise对象被创建, 执行器内部的函数就同步启动了,
但是<code>then</code>/<code>catch</code>并不会在状态变化之后同步执行,
所以Promise在状态变化之后仍然可以指定回调函数, 例如 <pre class="language-js" data-language="js"><code class="language-js">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Before Promise"</span><span class="token punctuation">)</span>

<span class="token keyword">const</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Promise ON"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Then0 ON"</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"After Then0"</span><span class="token punctuation">)</span>

p<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Then1 ON"</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"After Then1"</span><span class="token punctuation">)</span>

p<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Then2 ON"</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"After Then2"</span><span class="token punctuation">)</span>

<span class="token comment">/*
* Promise ON
* After Then0
* After Then1
* After Then2
* Then0 ON
* Then1 ON
* Then2 ON
*/</span></code></pre></p>
<h4 id="为什么要使用promise">为什么要使用Promise</h4>
<ul>
<li>Promise指定回调函数十分灵活(体现在时间上), 例如 <pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">// 对于使用回调函数, 必须在调用的时候指定</span>
<span class="token function">creatMusic</span><span class="token punctuation">(</span>config<span class="token punctuation">,</span> onSuccess<span class="token punctuation">,</span> onFaile<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 对于Promise, 可以随意指定回调</span>
<span class="token keyword">const</span> t <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Do other things</span>
t<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
<li>支持链式调用, 解决了回调地狱(但是还是存在回调函数的问题,
所以终极解决方案是async/await)</li>
<li>支持异常穿透 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> t <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
t<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
t<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
t<span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// t输出reject直接到这里, 忽略then</span></code></pre></li>
</ul>
<h4 id="如何使用promise">如何使用Promise</h4>
<p><strong>API</strong></p>
<p>直接看MDN</p>
<ul>
<li>Promise.all()</li>
<li>Promise.allSettled()</li>
<li>Promise.any()</li>
<li>Promise.prototype.catch()</li>
<li>Promise.prototype.finally()</li>
<li>Promise.race()</li>
<li>Promise.reject()</li>
<li>Promise.resolve()</li>
<li>Promise.prototype.then()</li>
</ul>
<p>首先应该认识到:</p>
<ul>
<li>Promise.all之类的函数只能由Promise函数对象调用</li>
<li>Promise.prototype.catch之类的函数可以由Promise实例调用
比较陌生的</li>
<li><code>new Promise.resolve(value)/reserve(reason)</code>, 语法糖
&lt;=&gt; <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">reserve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span><span class="token function">reserve</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span></code></pre></li>
<li><code>Promise.all([promise1,promise2...])</code>参数是一个Promise对象的数组,
返回一个Promise,
所有的Promise都reserve才是reserve(value是所有Promise的reason的数组),
其他情况都会reject(reason是第一个失败的promise的reason)
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">[</span>p1<span class="token punctuation">,</span>p2<span class="token punctuation">,</span>p3<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span>
    Promise<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">"A"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    Promise<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">"B"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token comment">// Promise.reject("B"),</span>
    Promise<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">"C"</span><span class="token punctuation">)</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> res <span class="token operator">=</span> Promise<span class="token punctuation">.</span><span class="token function">all</span><span class="token punctuation">(</span><span class="token punctuation">[</span>p1<span class="token punctuation">,</span>p2<span class="token punctuation">,</span>p3<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>
    <span class="token parameter">value</span><span class="token operator">=></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token parameter">reason</span><span class="token operator">=></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>reason<span class="token punctuation">)</span>
<span class="token punctuation">)</span></code></pre></li>
<li><code>Promise.race([promise1,promise2,...])</code>参数是Promise对象的数组,
返回最先变化状态的Promise</li>
</ul>
<p><strong>几个关键的点</strong></p>
<ul>
<li><p>改变Promise的状态与指定回调函数没有顺序要求, 但是存在一定的区别
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">reserve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  <span class="token function">reserve</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>

<span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">reserve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span><span class="token function">reserve</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span></code></pre> 上面代码是先修改状态(因为执行器函数是同步回调函数),
这样等到JS执行到then的时候Promise已经是reserved, 直接执行then.
但是下面的代码是先执行then, 后reserverd, 这时JS读取到then,
但是Promise还是peding状态, 所以会吧then中的函数先存储起来</p></li>
<li><p>区分执行器函数, then, 回调函数: 执行器函数是同步回调函数,
then是同步的(这里的then只是注册了两个回调函数, 当然是同步的了),
但是then中的回调函数是异步执行的</p></li>
<li><p>注意如果有多个then, 下一个then的数据来自上一个then的返回值,
下一个是reserve还是reject取决于上一个then的结果是reserve还是reject
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">reserve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  <span class="token function">reserve</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>
  <span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T1R"</span><span class="token punctuation">,</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token parameter">reason</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T1J"</span><span class="token punctuation">,</span>reason<span class="token punctuation">)</span><span class="token punctuation">&#125;</span>
<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>
  <span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T2R"</span><span class="token punctuation">,</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token parameter">reason</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T2J"</span><span class="token punctuation">,</span>reason<span class="token punctuation">)</span><span class="token punctuation">&#125;</span>
<span class="token punctuation">)</span>
<span class="token comment">/*
 * T1R 1
 * T2R undefined
 */</span></code></pre> 与 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">reserve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  <span class="token function">reject</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>
  <span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T1R"</span><span class="token punctuation">,</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token parameter">reason</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T1J"</span><span class="token punctuation">,</span>reason<span class="token punctuation">)</span><span class="token punctuation">&#125;</span>
<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>
  <span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T2R"</span><span class="token punctuation">,</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token parameter">reason</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T2J"</span><span class="token punctuation">,</span>reason<span class="token punctuation">)</span><span class="token punctuation">&#125;</span>
<span class="token punctuation">)</span>
<span class="token comment">/*
 * T1J 1
 * T2R undefined
 */</span></code></pre></p></li>
<li><p>函数穿透问题: 我们知道Promise的then可以只写一半, 比如
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">reserve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  <span class="token keyword">throw</span> <span class="token number">10</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>
  <span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T1R"</span><span class="token punctuation">,</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span>
<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>
  <span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T2R"</span><span class="token punctuation">,</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span>
<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span>
  <span class="token parameter">reason</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T1F"</span><span class="token punctuation">,</span>reason<span class="token punctuation">)</span><span class="token punctuation">&#125;</span>
<span class="token punctuation">)</span></code></pre> 在执行的时候, JS会直接跳转到catch函数执行回调函数,
JS并不是因为看then中没有catch的代码就不执行了, 而是这两个参数都有默认值,
可以理解为JS会默认将 <pre class="language-js" data-language="js"><code class="language-js">promise<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>
  <span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T2R"</span><span class="token punctuation">,</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span>
<span class="token punctuation">)</span></code></pre> 补全为 <pre class="language-js" data-language="js"><code class="language-js">promise<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>
  <span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"T2R"</span><span class="token punctuation">,</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token parameter">reason</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span><span class="token keyword">throw</span> reason<span class="token punctuation">;</span><span class="token punctuation">&#125;</span>
<span class="token punctuation">)</span></code></pre></p></li>
<li><p>如何终止Promise链的执行:
只需要在希望终止的函数中返回一个<code>Promise&lt;pading&gt;</code>让他永远不能变化<code>return new Promise(()=&gt;&#123;&#125;)</code></p></li>
</ul>
<h3 id="手写promise">手写Promise</h3>
<p>定义了一个Bromise模块 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">Bromise</span><span class="token punctuation">(</span><span class="token parameter">executer</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token constant">PENDING</span> <span class="token operator">=</span> <span class="token string">'pending'</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token constant">RESOLVED</span> <span class="token operator">=</span> <span class="token string">'resolved'</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token constant">REJECTED</span> <span class="token operator">=</span> <span class="token string">'rejected'</span><span class="token punctuation">;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>statue <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token constant">PENDING</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>data <span class="token operator">=</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>callbacks <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">resolve</span> <span class="token operator">=</span> <span class="token parameter">value</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>statue <span class="token operator">!==</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token constant">PENDING</span><span class="token punctuation">)</span><span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>statue <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token constant">RESOLVED</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>data <span class="token operator">=</span> value<span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>callbacks<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
            <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
                <span class="token keyword">this</span><span class="token punctuation">.</span>callbacks<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">d</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
                    d<span class="token punctuation">.</span><span class="token function">onResolved</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">reject</span> <span class="token operator">=</span> <span class="token parameter">reason</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>statue <span class="token operator">!==</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token constant">PENDING</span><span class="token punctuation">)</span><span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>statue <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token constant">REJECTED</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>data <span class="token operator">=</span> reason<span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>callbacks<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
            <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
                <span class="token keyword">this</span><span class="token punctuation">.</span>callbacks<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">d</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
                    d<span class="token punctuation">.</span><span class="token function">onRejected</span><span class="token punctuation">(</span>reason<span class="token punctuation">)</span><span class="token punctuation">;</span> 
                <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>

    <span class="token keyword">try</span><span class="token punctuation">&#123;</span>
        <span class="token function">executer</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span><span class="token keyword">this</span><span class="token punctuation">.</span>resolve<span class="token punctuation">,</span><span class="token keyword">this</span><span class="token punctuation">.</span>reject<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token keyword">catch</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">reject</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token class-name">Bromise</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">handle</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">callback</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">try</span><span class="token punctuation">&#123;</span>
        <span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token function">callback</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>result <span class="token keyword">instanceof</span> <span class="token class-name">Bromise</span><span class="token punctuation">)</span>
            result<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>resolve<span class="token punctuation">,</span><span class="token keyword">this</span><span class="token punctuation">.</span>reject<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">else</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token keyword">catch</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">reject</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

Bromise<span class="token punctuation">.</span><span class="token function-variable function">resolve</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>value <span class="token keyword">instanceof</span> <span class="token class-name">Bromise</span><span class="token punctuation">)</span>
        value<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>resolve<span class="token punctuation">,</span><span class="token keyword">this</span><span class="token punctuation">.</span>reject<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Bromise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span><span class="token function">resolve</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

Bromise<span class="token punctuation">.</span><span class="token function-variable function">reject</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">reason</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Bromise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span><span class="token function">reject</span><span class="token punctuation">(</span>reason<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token class-name">Bromise</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">then</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">onResolved<span class="token punctuation">,</span> onRejected</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">let</span> self <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Bromise</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>

        <span class="token keyword">let</span> self2 <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> onResolved <span class="token operator">!==</span> <span class="token string">'function'</span><span class="token punctuation">)</span><span class="token function-variable function">onResolved</span> <span class="token operator">=</span> <span class="token parameter">value</span> <span class="token operator">=></span> value<span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> onRejected <span class="token operator">!==</span> <span class="token string">'function'</span><span class="token punctuation">)</span><span class="token function-variable function">onRejected</span> <span class="token operator">=</span> <span class="token parameter">reason</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span><span class="token function">reject</span><span class="token punctuation">(</span>reason<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>self<span class="token punctuation">.</span>statue <span class="token operator">==</span> self<span class="token punctuation">.</span><span class="token constant">RESOLVED</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>self2<span class="token punctuation">.</span><span class="token function">handle</span><span class="token punctuation">(</span>onResolved<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span>
        <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span>self<span class="token punctuation">.</span>statue <span class="token operator">==</span> self<span class="token punctuation">.</span><span class="token constant">REJECTED</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>self2<span class="token punctuation">.</span><span class="token function">handle</span><span class="token punctuation">(</span>onRejected<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span>
        <span class="token keyword">else</span><span class="token punctuation">&#123;</span>
            self<span class="token punctuation">.</span>callbacks<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span><span class="token comment">// ! bug</span>
                <span class="token function">onResolved</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>self<span class="token punctuation">.</span><span class="token function">handle</span><span class="token punctuation">(</span>onResolved<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
                <span class="token function">onRejected</span><span class="token punctuation">(</span><span class="token parameter">reason</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>self<span class="token punctuation">.</span><span class="token function">handle</span><span class="token punctuation">(</span>onRejected<span class="token punctuation">)</span><span class="token punctuation">&#125;</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token class-name">Bromise</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">catch</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">onRejected</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">undefined</span><span class="token punctuation">,</span>onRejected<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

Bromise<span class="token punctuation">.</span><span class="token function-variable function">all</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">bromises</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">let</span> lengs <span class="token operator">=</span> bromises<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
    <span class="token keyword">let</span> cnt <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token keyword">let</span> results <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Array</span><span class="token punctuation">(</span>lengs<span class="token punctuation">)</span><span class="token punctuation">;</span>
    bromises<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">d<span class="token punctuation">,</span>i</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
        d<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
            results<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span>
            <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">++</span>cnt <span class="token operator">==</span> lengs<span class="token punctuation">)</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>results<span class="token punctuation">)</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token parameter">reason</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">reject</span><span class="token punctuation">(</span>reason<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

Bromise<span class="token punctuation">.</span><span class="token function-variable function">race</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">bromises</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    bromises<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">d<span class="token punctuation">,</span>i</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
        d<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token operator">=></span><span class="token punctuation">&#123;</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token parameter">reason</span><span class="token operator">=></span><span class="token punctuation">&#123;</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">reject</span><span class="token punctuation">(</span>reason<span class="token punctuation">)</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> Bromise<span class="token punctuation">;</span></code></pre></p>
<h3 id="asyncawait">async&amp;await</h3>
<ul>
<li>可以使用<code>async function</code>的方式定义一个异步函数,
函数被async修饰后会返回Promise对象(支持自动转换,
规则与<code>Promise.resolve()</code>一样)</li>
<li>可以在async函数中使用<code>await 表达式</code>的方式等待一个Promise(表达式的值不一定是一个Promise,
但是可以自动转换, 规则与<code>Promise.resolve()</code>一样)</li>
</ul>
<p>相当于是一个Promise的语法糖</p>
<h3 id="宏队列与微队列">宏队列与微队列</h3>
<p>在JS中实际上有两个事件队列, 宏队列与微队列,
管理器会将不同人物放入不同的队列. 微队列中仅存放微任务的回调,
例如promise的回调、MutationObserve的回调, 而宏队列存放宏任务的回调,
例如定时器回调 、DOM事件回调、ajax回调</p>
<p>JS是单线程的, 在执行过程中, JS会先执行同步代码,
然后执行微队列中的人物, 最后执行宏队列中任务,
在每次执行宏队列中的人物之前都要确保微队列为空,
否则先执行完毕微队列再执行人物</p>
<h3 id="面试题">面试题</h3>
<p>注意在pending下的then与在Resolved/Rejected下的then的区别,
<code>Resolved.then.then</code>不会立即执行</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>      <span class="token comment">// Step 1: 注册宏队列[TimeOut]</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>                <span class="token comment">//      Step 11: 执行宏队列</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>

<span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>   <span class="token comment">// Step 2: Promise的executer是同步回调直接执行</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>               <span class="token comment">// Step 3: 直接同步输出</span>
    <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>                    <span class="token comment">// Step 4: 修改状态</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>       <span class="token comment">// Step 5: 上一个Promise是Resolved, 所以加入微队列[then]</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>               <span class="token comment">//      Step 9: 输出结果, 情况微队列, 执行resolve, 注册下一个任务到微队列[then2]</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>       <span class="token comment">// Step 6: 上一个Promise(指的是上一个then)是pending, 将函数加入callbacks数组, 不注册宏队列,微队列</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>               <span class="token comment">//      Step 10: 优先执行微队列输出结果</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span>                    <span class="token comment">// Step 7: 同步执行输出</span>
                                  <span class="token comment">// Step 8: 宏队列[TimeOut], 微队列[then]</span></code></pre>
<p>结果为25341</p>

    </div>

    
    
    
      


    <footer class="post-footer">
          <div class="reward-container">
  <div></div>
  <button>
    赞赏
  </button>
  <div class="post-reward">
      <div>
        <img src="/images/wechatpay.png" alt="Liu Kairui 微信">
        <span>微信</span>
      </div>
      <div>
        <img src="/images/alipay.png" alt="Liu Kairui 支付宝">
        <span>支付宝</span>
      </div>

  </div>
</div>

          

<div class="post-copyright">
<ul>
  <li class="post-copyright-author">
      <strong>本文作者： </strong>Liu Kairui
  </li>
  <li class="post-copyright-link">
      <strong>本文链接：</strong>
      <a href="http://liukairui.me/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/" title="JavaScript进阶版笔记">http://liukairui.me/article/JavaScript进阶版笔记/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>

          <div class="post-tags">
              <a href="/tags/%E5%89%8D%E7%AB%AF/" rel="tag"><i class="fa fa-tag"></i> 前端</a>
              <a href="/tags/%E7%AC%94%E8%AE%B0/" rel="tag"><i class="fa fa-tag"></i> 笔记</a>
              <a href="/tags/JavaScript/" rel="tag"><i class="fa fa-tag"></i> JavaScript</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/article/JavaScript%E5%9F%BA%E7%A1%80%E7%89%88%E7%AC%94%E8%AE%B0/" rel="prev" title="JavaScript基础版笔记">
                  <i class="fa fa-chevron-left"></i> JavaScript基础版笔记
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/article/jQuery%E7%AC%94%E8%AE%B0/" rel="next" title="jQuery笔记">
                  jQuery笔记 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






    <div class="comments" id="valine-comments"></div>
</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 2019 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Liu Kairui</span>
</div>
<div class="busuanzi-count">
    <span class="post-meta-item" id="busuanzi_container_site_uv">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-item" id="busuanzi_container_site_pv">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>
  <div class="addthis_inline_share_toolbox">
    <script src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-6231eb6f709fc868" async="async"></script>
  </div><script
  async
  src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"
></script>

 
<script src="https://cdn.jsdelivr.net/npm/moment@2.22.2/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment-precise-range-plugin@1.3.0/moment-precise-range.min.js"></script>
<script>
  function timer() {
    var ages = moment.preciseDiff(moment(),moment(20201101,"YYYYMMDD"));
    ages = ages.replace(/years?/, "年");
    ages = ages.replace(/months?/, "月");
    ages = ages.replace(/days?/, "天");
    ages = ages.replace(/hours?/, "小时");
    ages = ages.replace(/minutes?/, "分");
    ages = ages.replace(/seconds?/, "秒");
    ages = ages.replace(/\d+/g, '<span class="daysCnt" style="color:#1890ff">$&</span>');
    div.innerHTML = `我已在此等候你 ${ages}`;
    div.className="workDays";
  }
  var div = document.createElement("div");
  //插入到copyright之后
  var copyright = document.querySelector(".copyright");
  document.querySelector(".footer-inner").insertBefore(div, copyright.nextSibling);
  timer();
  setInterval("timer()",1000)
</script>



    </div>
  </footer>

  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/@next-theme/pjax@0.5.0/pjax.min.js" integrity="sha256-3NkoLDrmHLTYj7csHIZSr0MHAFTXth7Ua/DDt4MRUAg=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js" integrity="sha256-yt2kYMy0w8AbtF89WXb2P1rfjcP/HTHLT7097U8Y5b8=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pangu/4.0.7/pangu.min.js"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  
<script src="https://cdn.jsdelivr.net/npm/hexo-generator-searchdb@1.4.0/dist/search.js" integrity="sha256-vXZMYLEqsROAXkEw93GGIvaB2ab+QW6w3+1ahD9nXXA=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>


  <script class="next-config" data-name="mermaid" type="application/json">{"enable":true,"theme":"forest","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.14.0/mermaid.min.js","integrity":"sha256-7wT34TI0pEBeEFoi4z+vhuSddGh6vUTMWdqJ2SDe2jg="}}</script>
  <script src="/js/third-party/tags/mermaid.js"></script>

  <script src="/js/third-party/fancybox.js"></script>

  <script src="/js/third-party/pace.js"></script>

  
  <script data-pjax async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>


  <script class="next-config" data-name="leancloud_visitors" type="application/json">{"enable":true,"app_id":"ABKlVtS4cyaWYEwunPyK3sXt-9Nh9j0Va","app_key":"xxGXdTTEGEVifs2TLB35844I","server_url":"https://abklvts4.lc-cn-e1-shared.com","security":false}</script>
  <script src="/js/third-party/statistics/lean-analytics.js"></script>


  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","mhchem":true,"js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.min.js"}}</script>
<script src="/js/third-party/math/mathjax.js"></script>


  <script src="https://cdnjs.cloudflare.com/ajax/libs/quicklink/2.2.0/quicklink.umd.js" integrity="sha256-4kQf9z5ntdQrzsBC3YSHnEz02Z9C1UeW/E9OgnvlzSY=" crossorigin="anonymous"></script>
  <script class="next-config" data-name="quicklink" type="application/json">{"enable":true,"home":false,"archive":false,"delay":true,"timeout":3000,"priority":true,"url":"http://liukairui.me/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/"}</script>
  <script src="/js/third-party/quicklink.js"></script>
<script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5.7/lib/darkmode-js.min.js"></script>

<script>
var options = {
  bottom: '64px',
  right: 'unset',
  left: '32px',
  time: '0.5s',
  mixColor: 'transparent',
  backgroundColor: 'transparent',
  buttonColorDark: '#100f2c',
  buttonColorLight: '#fff',
  saveInCookies: true,
  label: '🌓',
  autoMatchOsTheme: true
}
const darkmode = new Darkmode(options);
window.darkmode = darkmode;
darkmode.showWidget();
</script>


<script class="next-config" data-name="valine" type="application/json">{"enable":true,"appId":"ABKlVtS4cyaWYEwunPyK3sXt-9Nh9j0Va","appKey":"xxGXdTTEGEVifs2TLB35844I","serverURLs":"https://abklvts4.lc-cn-e1-shared.com","placeholder":"请开始你的表演","avatar":"identicon","meta":["nick","mail","link"],"pageSize":10,"lang":"zh-CN","visitor":false,"comment_count":true,"recordIP":true,"enableQQ":true,"requiredFields":[],"el":"#valine-comments","path":"/article/JavaScript%E8%BF%9B%E9%98%B6%E7%89%88%E7%AC%94%E8%AE%B0/"}</script>
<script>
document.addEventListener('page:loaded', () => {
  NexT.utils.loadComments(CONFIG.valine.el)
    .then(() => NexT.utils.getScript(
      'https://cdn.jsdelivr.net/npm/valine@1.4.14/dist/Valine.min.js',
      { condition: window.Valine }
    ))
    .then(() => {
      new Valine(CONFIG.valine);
    });
});
</script>


  <script async src="/js/fireworks.js"></script>




  <script src="/js/activate-power-mode.min.js"></script>
  <script>
    POWERMODE.colorful = true;
    POWERMODE.shake = false;
    document.body.addEventListener('input', POWERMODE);
  </script>




  <script src="/js/wobblewindow.js"></script>
  <script>
    //只在桌面版网页启用特效 记得同步到header.njk
    if( window.innerWidth > 768  ){
      $(document).ready(function () {
        
          $('body>main>header').wobbleWindow({
            radius: 50,
            movementTop: false,
            movementLeft: false,
            movementRight: false,
            debug: false,
          });
        

        //
        //  $('body header>aside').wobbleWindow({
        //    radius: 50,
        //    movementLeft: false,
        //    movementTop: false,
        //    movementBottom: false,
        //    position: 'fixed',
        //    debug: false,
        //  });
        //

        
          $('body>footer').wobbleWindow({
            radius: 50,
            movementBottom: false,
            movementLeft: false,
            movementRight: false,
            debug: false,
          });
        
      });
    }
  </script>


 
<script>
  $(document).ready(function(){
    var beian = document.querySelector(".footer-inner > .beian > a");
    var cpr=document.querySelector(".footer-inner > .copyright");
    var cnz=document.querySelector(".workDays");//.parentNode;
    var bsz=document.querySelector(".busuanzi-count");
    if(cnz!=null&&bsz!=null)
      cnz.parentNode.insertBefore(bsz,cnz);
    if(bsz == null || bsz == undefined || document.querySelector("#busuanzi_value_site_pv").innerText=="" || document.querySelector("#busuanzi_value_site_uv").innerText == "")
      bsz.remove();
    checkIndex();
    if(beian){cpr.classList.add('split-line');cpr.appendChild(beian);}
  })
  $(document).on('pjax:complete',checkIndex);
</script>



<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"log":false,"model":{"jsonPath":"/live2dw/assets/hijiki.model.json"},"display":{"position":"right","width":150,"height":300},"mobile":{"show":false},"react":{"opacity":0.7}});</script></body>
</html>
